(function(){


    var util = YAHOO.util,lang = YAHOO.lang;
    var Event = util.Event, Dom = util.Dom, Connect = util.Connect, JSON = lang.JSON,widget = YAHOO.widget;

/**
 * The WebUIWiringEditor class provides a full page interface 
 * @class WebUIWiringEditor
 * @constructor
 * @author Igor Lazarev
 * @param {Object} options
 * @param {boolean} guestMode
 */


WireIt.WebUIWiringEditor = function(options, guestMode) {// can't do a proper parent constructor call due to this.layer expression in the parent
     
    this.guestMode = guestMode

	 /**
	  * Hash object to reference module definitions by their name
	  * @property modulesByName
	  * @type {Object}
	  */
    this.modulesByName = {};

					
    // set the default options
    this.setOptions(options);

    /**
     * Container DOM element
     * @property el
     */
    this.el = Dom.get(options.parentEl);

    /**
     * @property helpPanel
     * @type {YAHOO.widget.Panel}
     */
    this.helpPanel = new widget.Panel('helpPanel', {
       	fixedcenter: true,
        draggable: true,
        visible: false,
        modal: true,
		zIndex: 100
     });
     this.helpPanel.render();
	 
	 this.loadingPanel = new widget.Panel('loadingPanel', {
        width:"150px",
		fixedcenter: true,
        draggable: true,
        visible: false,
        modal: true,
		zIndex: 100
	});
	
	this.loadingPanel.setHeader("Loading"); 
	this.loadingPanel.setBody('Please wait...');
	this.loadingPanel.render(document.body);
	
	this.debugPanel = new YAHOO.widget.Panel("debugWindow", { 
			width:"810px",  
			modal: false,
			fixedcenter: true,  
			constraintoviewport: true,  
			close:true, 
			zIndex : "100",
			draggable:true} );
		 			 			 
	this.debugPanel.setHeader("Debug console"); 
	this.debugPanel.setBody("<div id='debugPanelBody'><form><textarea name ='debugConsole' id ='console' ROWS=30 COLS=108 READONLY=TRUE>"+"Console started.. \n"+"</textarea></form></div></div>");
	this.debugPanel.render(document.body);
	
	this.debugPanel.hide();
	
    
    /**
     * @property layout
     * @type {YAHOO.widget.Layout}
     */
    this.layout = new widget.Layout(this.el, this.options.layoutOptions);
    this.layout.render();
	//module lists
	this.antiprismModules = options.antiprism || [];
	this.LPModules = options.LP_Solvers || [];
	this.NeosModules = options.Neos || [];
	this.miscModules = options.Misc || [];
	
	 // Right accordion
    this.renderAccordion();
	//Left Accordion
	this.renderLeftAccordion();
		
    /**
     * @property layer
     * @type {WireIt.Layer}
     */
    this.layer = new WireIt.WebUILayer(this.options.layerOptions);
	
	this.layer.eventChanged.subscribe(this.onLayerChanged, this, true);
	
	 /**
	  * @property leftEl
	  * @type {DOMElement}
	  */
    this.leftEl = Dom.get('left');
	this.generalDiv = Dom.get('generalDiv');
	this.antiprismDiv = Dom.get('antiprismDiv');
	this.LPDiv = Dom.get('LPDiv');
	this.NeosDiv = Dom.get('NeosDiv');
	this.miscDiv = Dom.get('miscDiv');
	this.composedDiv = Dom.get('composedDiv');
	
    // Render module list
    this.buildModulesList();
	this.buildAntiprismModulesList();
	this.buildLPModulesList();
	this.buildNeosModulesList();
	this.buildMiscModulesList();
	this.buildComposedModulesList();
	
    // Render buttons
    this.renderButtons();

 	 // Saved status
    this.renderSavedStatus();
	
    // Properties Form
    this.renderPropertiesForm();
		
	this.renderTaskPropertiesForm();
	this.renderIDForm();
	this.renderInstanceForm();

};

YAHOO.lang.extend(WireIt.WebUIWiringEditor, WireIt.WiringEditor, {
				
	setOptions: function(options){
		WireIt.WebUIWiringEditor.superclass.setOptions.call(this, options);
		
		this.options.taskPropertiesFields = options.taskPropertiesFields;
		this.options.IDFields = options.IDFields;
		this.options.instanceFields = options.instanceFields;
	},
	
	 
	 renderTaskPropertiesForm: function() {
	 	   this.taskPropertiesForm = new inputEx.Group({
	       parentEl: YAHOO.util.Dom.get('taskPropertiesForm'),
	       fields: this.options.taskPropertiesFields
	    });
	
		this.layer.eventContainerFocused.subscribe(this.onFocusedEvent,this, true);
		
		this.taskPropertiesForm.updatedEvt.subscribe(function(e,value) {
			var container = this.focusedContainer;
			var signatureField = this.taskPropertiesForm.getFieldByName("signature");
	
			if ((typeof(container)!="undefined")&&(typeof(container.textarea)!="undefined")&&(container.textarea.value != signatureField.getValue())){
				container.textarea.value = signatureField.getValue();
				container.createTerminals();// parse the textarea
			}
		}, this, true);
		
	},
	
	 
	renderIDForm: function() {
	    this.IDForm = new inputEx.Group({
	       parentEl: YAHOO.util.Dom.get('IDForm'),
	       fields: this.options.IDFields
	    }); 
	},
	
	renderInstanceForm: function() {
	    this.instanceForm = new inputEx.Group({
	       parentEl: YAHOO.util.Dom.get('instanceForm'),
	       fields: this.options.instanceFields
	    }); 
	},
	
	buildModulesList: function() {
		WireIt.WebUIWiringEditor.superclass.buildModulesList.call(this);
	},
	

	addModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
	      div.appendChild( WireIt.cn('span', null, null, module.name) );
	
	      var ddProxy = new WireIt.ModuleProxy(div, this);
	      ddProxy._module = module;
	
	     this.generalDiv.appendChild(div);
	},

	buildAntiprismModulesList: function(){
		var antiprismModules = this.antiprismModules;
     for(var i = 0 ; i < antiprismModules.length ; i++) {
		  this.addAntiprismModuleToList(antiprismModules[i]);
     }
	},
		
	addAntiprismModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
	      div.appendChild( WireIt.cn('span', null, null, module.name) );
	
	      var ddProxy = new WireIt.ModuleProxy(div, this);
	      ddProxy._module = module;
	
	     this.antiprismDiv.appendChild(div);
	},

	buildLPModulesList: function(){
		var LPModules = this.LPModules;
     for(var i = 0 ; i < LPModules.length ; i++) {
		  this.addLPModuleToList(LPModules[i]);
     }
	},
		
	addLPModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
	      div.appendChild( WireIt.cn('span', null, null, module.name) );
	
	      var ddProxy = new WireIt.ModuleProxy(div, this);
	      ddProxy._module = module;
	
	     this.LPDiv.appendChild(div);
	},
	
	buildNeosModulesList: function(){
		var NeosModules = this.NeosModules;
     for(var i = 0 ; i < NeosModules.length ; i++) {
		  this.addNeosModuleToList(NeosModules[i]);
     }
	},
		
	addNeosModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
	      div.appendChild( WireIt.cn('span', null, null, module.name) );
	
	      var ddProxy = new WireIt.ModuleProxy(div, this);
	      ddProxy._module = module;
	
	     this.NeosDiv.appendChild(div);
	},
	
	buildMiscModulesList: function(){
		var miscModules = this.miscModules;
     for(var i = 0 ; i < miscModules.length ; i++) {
		  this.addMiscModuleToList(miscModules[i]);
     }
	},
		
	addMiscModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
	      div.appendChild( WireIt.cn('span', null, null, module.name) );
	
	      var ddProxy = new WireIt.ModuleProxy(div, this);
	      ddProxy._module = module;
	
	     this.miscDiv.appendChild(div);
	},
	
	buildComposedModulesList: function(){
		
		this.composedDiv.innerHTML = '';
		
		var composedModules = new Array();
     	    new Ajax.Request (location.href+'wf/', { //a heisenbug in IE + Chrome Frame
			method:'get',
			requestHeaders: {Accept: 'application/json'},
			onSuccess: function(transport){
				var workflows = YAHOO.lang.JSON.parse(transport.responseText);
				
				for(var i=0;i<workflows.length;i++){
	 				var composedModule = workflows[i];
					composedModules.push('{"name":"'+composedModule.name+'","container":{"xtype": "Workflow.Container","service":"'+location.href+'services/'+composedModule.file+'"}}');
				}
		
				function sortByName(a, b) {
    				var x = JSON.parse(a).name.toLowerCase();
    				var y = JSON.parse(b).name.toLowerCase();
    				return ((x < y) ? -1 : ((x > y) ? 1 : 0));
				}
				
				composedModules.sort(sortByName);
				
				for(var i = 0 ; i < composedModules.length ; i++) {
		  			this.addComposedModuleToList(YAHOO.lang.JSON.parse(composedModules[i]));
     			}
									
			}.bind(this),
			
			onFailure: function(transport){ 
	
				var response = transport.responseText || "no response text";
				var url = location.href+'wf/';
				  if (transport.status==404) {
				   this.log(("404 error\nUrl "+url));
	
				   } else if (transport.status==400) {
				   alert("mistake in url "+url+"\n"+response);
				   this.log("mistake in url "+url+"\n"+response);
				   } else {
					   //do nothing
					   this.log('Could not load data from url '+transport.status+"\n"+response); }
				}.bind(this)
		});
	},
		
	addComposedModuleToList: function(module) {
		var div = WireIt.cn('div', {className: "WiringEditor-module"});
	      if(module.container.icon) {
	         div.appendChild( WireIt.cn('img',{src: module.container.icon}) );
	      }
		  if(module.name.length>23){
		  	module.name = module.name.substring(0,23)+"...";
		  }
			
		  div.appendChild( WireIt.cn('span', null, null, module.name) );
	      var ddProxy = new WireIt.ModuleProxy(div, this);
		  ddProxy._module = module;
		  this.composedDiv.appendChild(div);

	},
	
	addModule: function(module, pos){
		try {
	       var containerConfig = module.container;
	       containerConfig.position = pos;
	       containerConfig.title = module.name;
	       var container = this.layer.addContainer(containerConfig);
	       Dom.addClass(container.el, "WiringEditor-module-"+module.name);
		   container.initType();
	    }
	    catch(ex) {
	       alert("Error Layer.addContainer: "+ ex.message);//script error is here
	       this.log("Error Layer.addContainer: "+ ex.message);
	    }  
	},
	
  /**
  * Toolbar
  * @method renderButtons
  */
	 
 
	 
	 renderButtons: function() {
	 			
	    var toolbar = Dom.get('toolbar');
	    // Buttons :
	    var newButton = new widget.Button({ id:"WiringEditor-newButton", container: toolbar, title:"Create new workflow" });
	    newButton.on("click", this.onNew, this, true);
	
		var listButton = new widget.Button({ id:"WiringEditor-listButton", container: toolbar, title:"Load workflow"});
	    listButton.on("click", this.onList, this, true);
	    
		var saveButton = new widget.Button({ id:"WiringEditor-saveButton", container: toolbar, title:"Save workflow"+(this.guestMode?" (Disabled in guest mode)":""), disabled: this.guestMode });
	    saveButton.on("click", this.onSave, this, true);
	
	    var deleteButton = new widget.Button({ id:"WiringEditor-deleteButton", container: toolbar, title:"Delete workflow"+(this.guestMode?" (Disabled in guest mode)":""), disabled: this.guestMode });
	    deleteButton.on("click", this.onDelete, this, true);
		
		var helpButton = new widget.Button({ id:"WiringEditor-helpButton", container: toolbar, title:"Show help panel" });
	    helpButton.on("click", this.onHelp, this, true);
		
		var exportButton = new YAHOO.widget.Button({ id:"WiringEditor-exportButton", container: toolbar, title:"Export workflow as JSON" });
		exportButton.on("click", this.onExport, this, true);
		
		var importButton = new YAHOO.widget.Button({ id:"WiringEditor-importButton", container: toolbar, title:"Import workflow as JSON" });
		importButton.on("click", this.onImport, this, true);
	
		var runButton = new widget.Button({id:"WiringEditor-runButton", container: toolbar, title: "Run workflow"+(this.guestMode?" (Disabled in guest mode)":""), disabled: this.guestMode });
	    runButton.on("click", this.onRun, this, true);
		
		var stopButton = new widget.Button({ id:"WiringEditor-stopButton", container: toolbar, title:"Stop workflow execution"+(this.guestMode?" (Disabled in guest mode)":""), disabled: this.guestMode });
	    stopButton.on("click", this.onStop, this, true);
		
		var connectButton = new widget.Button({ id:"WiringEditor-connectButton", container: toolbar, title:"Connect to running workflow instance"+(this.guestMode?" (Disabled in guest mode)":""), disabled: this.guestMode });
	    connectButton.on("click", this.onConnect, this, true);
		
		var collapseButton = new widget.Button({id:"WiringEditor-collapseButton", container: toolbar, title:"Collapse all inputs and outputs" });
	    collapseButton.on("click", this.onCollapse, this, true);
		
		var expandButton = new widget.Button({id:"WiringEditor-expandButton", container: toolbar, title:"Expand all inputs and outputs" });
	    expandButton.on("click", this.onExpand, this, true);
		
		var debugButton = new widget.Button({id:"WiringEditor-debugButton", container: toolbar, title:"Open debug console" });
	    debugButton.on("click", this.onDebug, this, true);
		
	 },
	
	renderSavedStatus: function() {
		var top = Dom.get('top');
		this.savedStatusEl = WireIt.cn('div', {className: 'savedStatus', title: 'Not saved'}, {display: 'none'}, "");
		top.appendChild(this.savedStatusEl);
	},
	
	 
	renderLeftAccordion: function(){
		this.leftAccordionView = new YAHOO.widget.AccordionView('leftAccordionView', {collapsible: true, expandable: true, width: '173px', animate: true, animationSpeed: '0.3'});

	},

	/**
	* save the current module
	* @method saveModule
	*/
	saveModule: function() {
	
	var value = this.getValue();
	   
	   if(value.name == "") {
	   alert("Please choose a name");
	   this.log("No name chosen. Saving cancelled");
	   return;
	}
	
	var valueString = YAHOO.lang.JSON.stringify(value);
	
	if (!this.saveFile){
	new Ajax.Request (location.href+'wf/', {
		method:'post',
		postBody: valueString,
		contentType: 'application/json',
	
		onSuccess: function(transport){
		var response = transport.responseText || "no response text";
		alert("Success! \n\n" + "Workflow saved. Name: " + response);
		this.log("Success! \n\n" + "Workflow saved. Name: " + response);
		this.markSaved();
		this.saveFile = response;
		
		this.IDForm.getFieldByName("ID").setValue(this.saveFile);
		
		this.buildComposedModulesList();
		
		}.bind(this),
		onFailure: function(transport){ 
			var url = location.href+'wf/';
			var response = transport.responseText || "no response text";
			  if (transport.status==404) {
			   alert("404 error\nUrl "+url);
			   this.log("404 error\nUrl "+url);
	
			   } else if (transport.status==400) {
			   alert("mistake in url "+url+"\n"+response);
			   this.log("mistake in url "+url+"\n"+response);
			   } else {
				   alert('Could not load data from url '+transport.status+"\n"+response);
				   this.log('Could not load data from url '+transport.status+"\n"+response);				    }
			}.bind(this)
	});
	}
	
	else {
		saveConfirmDialog = new widget.Dialog("loadWindow",  
						{ width : "400px",
						  modal: true,
						  fixedcenter : true, 
						  constraintoviewport : true,
						  close:true,
						  postmethod : "form",
						  zIndex : "100",
						  } );
						 
		var handleOverwrite = function(){
			new Ajax.Request (location.href+'wf/'+this.saveFile+'?method=put', {
				method:'post',
				postBody: valueString,
				contentType: 'application/json',
	
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				alert("Success! \n\n" + "Workflow overwritten.");
				this.log("Success! \n\n" + "Workflow overwritten.");
				this.markSaved();
				
				}.bind(this),
				onFailure: function(transport){ 
					var url = location.href+'wf/'+this.saveFile+'?method=put';
					var response = transport.responseText || "no response text";
					  if (transport.status==404) {
					   alert("404 error\nUrl "+url);
					   this.log("404 error\nUrl "+url);
	
					   } else if (transport.status==400) {
					   alert("mistake in url "+url+"\n"+response);
					   this.log("mistake in url "+url+"\n"+response);
					   } else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response); }
					}.bind(this)
			});
			saveConfirmDialog.hide();
		}.bind(this);
		
		var handleSaveAs = function(){
				new Ajax.Request (location.href+'wf/', {
				method:'post',
				postBody: valueString,
				contentType: 'application/json',
	
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				alert("Success! \n\n" + "Workflow saved. Name: " + response);
				this.log("Success! \n\n" + "Workflow saved. Name: " + response);
				this.markSaved();
				this.saveFile = response;
				
				this.IDForm.getFieldByName("ID").setValue(this.saveFile);
				
				this.buildComposedModulesList();
				
				}.bind(this),
				onFailure: function(transport){ 
					var url = location.href+'wf/';
					var response = transport.responseText || "no response text";
					  if (transport.status==404) {
					   alert("404 error\nUrl "+url);
					   this.log("404 error\nUrl "+url);
	
					   } else if (transport.status==400) {
					   alert("mistake in url "+url+"\n"+response);
					   this.log("mistake in url "+url+"\n"+response);
					   } else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response); }
					}.bind(this)
		});
			saveConfirmDialog.hide();
		}.bind(this);
		
		var handleCancel = function(){
			saveConfirmDialog.hide();
		}.bind(this);
		
		var confirmButtons = [{ text:"Overwrite", handler:handleOverwrite, isDefault:true }, {text:"Save as new", handler:handleSaveAs, isDefault:true}, {text:"Cancel", handler:handleCancel, isDefault:true} ];
			
		
		saveConfirmDialog.cfg.queueProperty("buttons", confirmButtons); 
		saveConfirmDialog.setHeader("Confirm overwrite"); 
		saveConfirmDialog.setBody("<div id='loadDialog'>Workflow exists. Overwrite?</div>");
		saveConfirmDialog.render(document.body);
		saveConfirmDialog.show();
	
	}
	
	},
	
	/**
	* @method onNew
	*/
	onNew: function() {
		WireIt.WebUIWiringEditor.superclass.onNew.call(this);
				
		this.taskPropertiesForm.clear();
		this.IDForm.clear();
		this.saveFile=undefined;
		this.markUnsaved();
	},
	
	 /**
	  * @method onDelete
	  */
	onDelete: function() {
	    if( confirm("Are you sure you want to delete this workflow?") ) {
			
			if(this.saveFile){
			new Ajax.Request (location.href+'wf/'+this.saveFile+'?method=delete', {
				method:'post',
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				alert("Success! \n\n" + "Workflow deleted");
				this.log("Success! \n\n" + "Workflow deleted");
				
				this.saveFile = undefined;
				this.markSaved();
				this.IDForm.clear();
							
				this.layer.removeAllContainers();
				this.propertiesForm.clear();
				this.taskPropertiesForm.clear();
				
				this.buildComposedModulesList();
				
				
				}.bind(this),
	
				onFailure: function(transport){ 
					var url = location.href+'wf/'+this.saveFile+'?method=delete'; 
					var response = transport.responseText || "no response text";
					if (transport.status==404) {
						this.log("404 error\nUrl "+url);
							
						} else if (transport.status==400) {
							alert("mistake in url "+url+"\n"+response);
							this.log("mistake in url "+url+"\n"+response);
						} else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response); }
						}.bind(this)
			});
			}
			else{
			alert ("Workflow is not saved yet!");
			this.log("Workflow is not saved yet!");
			}
			
		}
	},
	 
	 onExport: function(){
		 myPanel = new YAHOO.widget.Panel("exportWindow", { 
					width:"610px",  
					modal: true,
					fixedcenter: true,  
					constraintoviewport: true,  
					close:true, 
					zIndex : "100",
					draggable:true} );

				 var wiringToString = YAHOO.lang.newJSON.stringify(this.getValue(),null,'\t'); //more complete, includes properties etc
				 			 			 
				 myPanel.setHeader("JSON export"); 
				 myPanel.setBody("<div id='myPanelBody'><form><textarea name ='jsonExport' ROWS=40 COLS=78 READONLY=TRUE>"+wiringToString+"</textarea></form></div></div>");
				 myPanel.render(document.body);
				   
				 myPanel.show();
	 },
 
	 onImport: function(){
	
	 	myDialog = new widget.Dialog("importWindow",  
						{ width : "600px",
						  modal: true,
						  fixedcenter : true, 
						  constraintoviewport : true,
						  close:true,
						  postmethod : "form",
						  zIndex : "100",
						  } );
			
	
			
			var myButtons = [ { text:"Submit", handler:{fn:this.onImportSubmit, obj: this, scope: this}, isDefault:true } ];
			
			myDialog.cfg.queueProperty("buttons", myButtons); 
			myDialog.setHeader("JSON import"); 
			myDialog.setBody("<div id='myDialog'><form><textarea name ='json' ROWS=5 COLS=78>Enter your JSON data here</textarea></form></div></div>");
			myDialog.render(document.body);
			myDialog.show(); 
	 },
	
	 /**
	  * @method onImportSubmit
	  * by Igor Lazarev
	  */
	  
	onImportSubmit: function() { 
	
	 	myDialog.hide();
		var jsonFile = myDialog.getData().json;
		var wiring = YAHOO.lang.JSON.parse(jsonFile);
		var pipe = wiring.working;
		
		this.loadWorkflow(pipe);
		this.markSaved();
		
		this.markUnsaved();
		
			
	
	},
	
	onLoad: function() {
		alert("1");
		loadDialog = new widget.Dialog("loadWindow",  
						{ width : "400px",
						  modal: true,
						  fixedcenter : true, 
						  constraintoviewport : true,
						  close:true,
						  postmethod : "form",
						  zIndex : "100",
						} );
				
		var handleLoad = function(){
			
			this.loadSubmit(loadDialog.getData().filename);
			loadDialog.hide();
			
		}.bind(this);
		
		var loadButtons = [ {text:"Load", handler:handleLoad, isDefault:true} ];
			
		loadDialog.cfg.queueProperty("buttons", loadButtons); 
		loadDialog.setHeader("Load workflow"); 
		loadDialog.setBody("<div id='loadDialog'><form><textarea name ='filename' ROWS=1 COLS=48>Enter filename</textarea></form></div></div>");
		loadDialog.render(document.body);
		loadDialog.show(); 
	 },

	
	loadSubmit: function(filename){
			var request = new Ajax.Request (location.href+'wf/'+ filename, {
			method:'get',
			requestHeaders: {Accept: 'application/json'},
			onSuccess: function(transport){
				var response = transport.responseText || "no response text";
	
				var wiring = YAHOO.lang.JSON.parse(response);
				
				var pipe = wiring.working;
							
				this.saveFile = filename;
				this.markSaved();
				this.IDForm.getFieldByName("ID").setValue(this.saveFile);
				this.loadWorkflow(pipe);
				
				this.markSaved();
					
			}.bind(this),
			
			onFailure: function(transport){ 
				var url = location.href+'wf/'+ filename;
				var response = transport.responseText || "no response text";
				  if (transport.status==404) {
				   alert("404 error\nUrl "+url);
				   this.log("404 error\nUrl "+url);
	
				   } else if (transport.status==400) {
				   alert("mistake in url "+url+"\n"+response);
				   this.log("mistake in url "+url+"\n"+response);
				   } else {
					   alert('Could not load data from url '+transport.status+"\n"+response);
					   this.log('Could not load data from url '+transport.status+"\n"+response); }
				}.bind(this)
		});

	},
	
	onList: function() {
	    new Ajax.Request (location.href+'wf/', { //a heisenbug in IE
			method:'get',
			requestHeaders: {Accept: 'application/json'},
			onSuccess: function(transport){
				this.pipes = YAHOO.lang.JSON.parse(transport.responseText);
				
				this.renderLoadPanel();
				this.updateLoadPanelList();
	            this.loadPanel.show();
				
			}.bind(this),
			
			onFailure: function(transport){
				var url = location.href+'wf/';
				var response = transport.responseText || "no response text";
				  if (transport.status==404) {
				   alert("404 error\nUrl "+url);
				   this.log("404 error\nUrl "+url);
	
				   } else if (transport.status==400) {
				   alert("mistake in url "+url+"\n"+response);
				   this.log("mistake in url "+url+"\n"+response);
				   } else {
					   alert('Could not load data from url '+transport.status+"\n"+response);
					   this.log('Could not load data from url '+transport.status+"\n"+response); }
				}.bind(this)
		});
	},
	
	onRun: function(){

	document.body.style.cursor = 'wait';
	this.onStop();
	this.log("Starting workflow execution..");
						
		var tasks = new Array;
		var outputs = new Array;
		var inputs = new Array;

		
		for (i=0;i<this.layer.containers.length;i++){
			if (this.layer.containers[i].options.title == "output"){
				outputs.push(this.layer.containers[i]);
			}
			else if (this.layer.containers[i].options.title == "input"){
				inputs.push(this.layer.containers[i]);
			}
		}
			
		//check whether outputs have unique names
		
		for (i=0;i<outputs.length;i++){

			var name = outputs[i].getValue().input.inputParams.name;
			var occurs = 0;
			for (i=0;i< outputs.length;i++){
				
				if (outputs[i].getValue().input.inputParams.name == name){
					occurs++;
				}

			}
				if (occurs>1){
					alert("Outputs must have unique names");
					this.log("Running cancelled. Outputs must have unique names");
					return null; 
				}
		}
		
		//check whether inputs have unique names
		
		for (i=0;i<inputs.length;i++){

			var name = inputs[i].getValue().input.inputParams.name;
			var occurs = 0;
			for (i=0;i< inputs.length;i++){
				
				if (inputs[i].getValue().input.inputParams.name == name){
					occurs++;
				}

			}
				if (occurs>1){
					alert("Inputs must have unique names");
					this.log("Running cancelled. Inputs must have unique names");
					return null; 
				}
		}
		
		//refresh states of all containers
		
		for (i=0;i<this.layer.containers.length;i++){
			this.layer.containers[i].initState();
		}
		//check if all containers are ready for execution
		
		for (i=0;i<this.layer.containers.length;i++){
			 if ((this.layer.containers[i].state=="UNREADY")||(this.layer.containers[i].state=="MISSING")){
				alert("Workflow is not ready for execution. Running cancelled");
				this.log("Workflow is not ready for execution. Running cancelled");
				return null;
			 }		 
			 
			 
			 if ((this.layer.containers[i].type == "Task")||(this.layer.containers[i].options.title == "Script")||(this.layer.containers[i].options.title == "JavaScript")||(this.layer.containers[i].options.title == "Python")){
				tasks.push(this.layer.containers[i]);
			 }

		}
		
		if (!this.saveFile) {

			var date = new Date();
			
			this.propertiesForm.getFieldByName("name").setValue("temporary " + date.getFullYear()+"."+date.getMonth()+"."+date.getDate()+" "+date.getHours()+":"+date.getMinutes());
			this.temporary = true;
			
			new Ajax.Request (location.href+'wf/', {
				method:'post',
				postBody: YAHOO.lang.JSON.stringify(this.getValue()),
				contentType: 'application/json',
			
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				this.saveFile = response;
				this.IDForm.getFieldByName("ID").setValue(this.saveFile);
				this.runRequest(tasks,outputs);
					
				}.bind(this),
				onFailure: function(transport){ 
					var url = location.href+'wf/'; 
					var response = transport.responseText || "no response text";
					  if (transport.status==404) {
					   alert("404 error\nUrl "+url);
					   this.log("404 error\nUrl "+url);
			
					   } else if (transport.status==400) {
					   alert("mistake in url "+url+"\n"+response);
					   this.log("mistake in url "+url+"\n"+response);
					   } else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response) }
					}.bind(this)
			});
		}
		else {
			this.temporary = false;
			this.runRequest(tasks,outputs);
		}
		

	},
	
	runRequest: function(tasks, outputs){
			new Ajax.Request (location.href+'services/' + this.saveFile, {//run the workflow
			method:'post',
	        postBody: YAHOO.lang.JSON.stringify(this.getInputValues()),
			contentType: 'application/json',
			onSuccess: function(transport){
				var status = transport.status;
			    var instanceURI =  transport.getHeader("Location");
				this.instanceURI = instanceURI;
				this.instanceForm.getFieldByName("instance").setValue(instanceURI);
				this.log("success! Status:" + status + " URI:" + instanceURI);				
				document.body.style.cursor = 'default';
				this.startRequests(instanceURI,tasks,outputs);
				}.bind(this),
			
			onFailure: function(transport){
				document.body.style.cursor = 'default';
				var url = location.href+'services/' + this.saveFile;
				var response = transport.responseText || "no response text";
				  if (transport.status==404) {
				   alert("404 error\nUrl "+url);
				   this.log("404 error\nUrl "+url);
	
				   } else if (transport.status==400) {
				   alert("mistake in url "+url+"\n"+response);
				   this.log("mistake in url "+url+"\n"+response);
				   } else {
					   alert('POST. Could not load data from url '+ url + "\n"+"Status: "+ transport.status +"\n"+response);
					   this.log('POST. Could not load data from url '+ url + "\n"+"Status: "+ transport.status +"\n"+response);}
				}.bind(this)
		});
	},
	
	
	onStop: function(){
		if(this.instanceURI&&this.pe){
			this.log("Stopping workflow execution..");
			this.pe.stop();
			new Ajax.Request (this.instanceURI+'?method=delete', {
				method:'post',
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				this.log("Success! " + "Workflow stopped");
       	
				this.returnToEditor();
				this.instanceForm.clear();
				}.bind(this),
				
				onFailure: function(transport){ 
				var response = transport.responseText || "no response text";
				var url = this.instanceURI+'?method=delete';
				if (transport.status==404) {

					this.log("404 error\nUrl "+url);

					} else if (transport.status==400) {
						alert("mistake in url "+url+"\n"+response);
						this.log("mistake in url "+url+"\n"+response);
					} else {
					   alert('Could not load data from url '+transport.status+"\n"+response);
					   this.log('Could not load data from url '+transport.status+"\n"+response); }
					}.bind(this)
			});
			
		}
		else{
			for (i = 0; i < this.layer.containers.length; i++) {
                		this.layer.containers[i].setReady();
            		}		
		}
	},
	
	onConnect: function(){
		connectDialog = new widget.Dialog("connectWindow",  
						{ width : "450px",
						  modal: true,
						  fixedcenter : true, 
						  constraintoviewport : true,
						  close:true,
						  postmethod : "form",
						  zIndex : "100",
						} );
		
		var handleConnect = function(){
			connectDialog.hide();
			this.loadingPanel.show();
			document.body.style.cursor = 'wait';
			var instanceURI = connectDialog.getData().instance;
			
			this.instanceForm.getFieldByName("instance").setValue(instanceURI);
			this.instanceURI = instanceURI;

			var fullID = instanceURI.split("services/")[1];
			var workflowID = fullID.split("/")[0];
			var instanceID = fullID.split("/")[1];
			
			this.loaded=false;
			this.loadSubmit(workflowID);
			
			
			new PeriodicalExecuter(function(ep){
				if(this.loaded == true){
				ep.stop();
				var tasks = new Array;
				var outputs = new Array;
				for (i=0;i<this.layer.containers.length;i++){
				
					if ((this.layer.containers[i].options.title == "Task")||(this.layer.containers[i].options.title == "Script")||(this.layer.containers[i].options.title == "JavaScript")||(this.layer.containers[i].options.title == "Python")){
						tasks.push(this.layer.containers[i]);
					}
					else if (this.layer.containers[i].options.title == "input"){
						this.layer.containers[i].setDone();
					
					}
					else if (this.layer.containers[i].options.title == "output"){
						outputs.push(this.layer.containers[i]);
					}
				}
			
			
			this.startRequests(instanceURI,tasks,outputs);
			this.loadingPanel.hide();
			document.body.style.cursor = 'default';

			}			
			}.bind(this), 0.5)			


		}.bind(this);
		
		var connectButtons = [ {text:"Load", handler:handleConnect, isDefault:true} ];
			
		connectDialog.cfg.queueProperty("buttons", connectButtons); 
		connectDialog.setHeader("Enter workflow instance URI"); 
		connectDialog.setBody("<div id='connectDialog'><form><textarea name ='instance' ROWS=1 COLS=48></textarea></form></div></div>");
		connectDialog.render(document.body);
		connectDialog.show(); 
	},
	
	onCollapse: function(){ //Collapse all inputs and outputs
		var outputs = new Array;
		var inputs = new Array;
		
		for (i=0;i<this.layer.containers.length;i++){
			if (this.layer.containers[i].options.title == "output"){
				outputs.push(this.layer.containers[i]);
			}
			else if (this.layer.containers[i].options.title == "input"){
				inputs.push(this.layer.containers[i]);
			}
		}
		
		for (i=0;i<inputs.length;i++){
			inputs[i].el.style.display='none';
			for (j = 0; j < inputs[i].wires.length; j++) {
				inputs[i].wires[j].element.style.display='none';
			}
		}
		
		for (i=0;i<outputs.length;i++){
			outputs[i].el.style.display='none';
				for (j = 0; j < outputs[i].wires.length; j++) {
				outputs[i].wires[j].element.style.display='none';
			}
		}
		
	},
	
	onExpand: function(){ //Expand all inputs and outputs
		var outputs = new Array;
		var inputs = new Array;
		
		for (i=0;i<this.layer.containers.length;i++){
			if (this.layer.containers[i].options.title == "output"){
				outputs.push(this.layer.containers[i]);
			}
			else if (this.layer.containers[i].options.title == "input"){
				inputs.push(this.layer.containers[i]);
			}
		}
		
		for (i=0;i<inputs.length;i++){
			inputs[i].el.style.display='block';
			for (j = 0; j < inputs[i].wires.length; j++) {
				inputs[i].wires[j].element.style.display='block';
			}
			inputs[i].redrawAllWires();
		}
		
		for (i=0;i<outputs.length;i++){
			outputs[i].el.style.display='block';
				for (j = 0; j < outputs[i].wires.length; j++) {
				outputs[i].wires[j].element.style.display='block';
			}
			outputs[i].redrawAllWires();
		}	
	},
	
	onDebug: function(){
		this.debugPanel.render(document.body);
		this.debugPanel.show();
	},
	
	startRequests: function(instanceURI, tasks,outputs){
		new PeriodicalExecuter(function(pe){
					for (i = 0; i < this.layer.containers.length; i++) {
						if (this.layer.containers[i].options.title == "input") {
							this.layer.containers[i].setDone();
						}
					}
					this.pe = pe;
					new Ajax.Request (instanceURI, {
					method:'get',
					requestHeaders: {Accept: 'application/json'},
					onSuccess: function(transport){
						var response = transport.responseText;
						if(response){
							var json = JSON.parse(response);
							if (json.state == "WAITING") {
								this.log ("Waiting for workflow execution..");
							}
							else if (json.state == "CANCELLED") {
								this.log ("Workflow execution cancelled");
								pe.stop();
								this.deleteTemporary();
							}
							else if (json.state == "FAILED") {
								this.log ("Workflow execution failed");
								pe.stop();
								this.deleteTemporary();
							}
							
							for (i=0;i<tasks.length;i++){
								if(json.tasks[i].state != tasks[i].state){
									if(json.tasks[i].state == "WAITING"){
										tasks[i].setWaiting();
										this.log("task "+i+" ("+tasks[i].getConfig().name+") is waiting");
									}
									
									else if(json.tasks[i].state == "RUNNING"){
										tasks[i].setRunning();
										this.log("task "+i+" ("+tasks[i].getConfig().name+") is running");
									}
									
									else if(json.tasks[i].state == "DONE"){
										tasks[i].setDone();
										this.log("task "+i+" ("+tasks[i].getConfig().name+") is done");
									}
																		
									else if(json.tasks[i].state == "CANCELLED"){
										tasks[i].setCancelled();
										this.log("task "+i+" ("+tasks[i].getConfig().name+") is cancelled");
									}
									
									else if(json.tasks[i].state == "FAILED"){
										tasks[i].setFailed();
										this.log("task "+i+" ("+tasks[i].getConfig().name+") is failed");
								
									}
									if (json.tasks[i].info) {
										this.log("task "+i+" ("+tasks[i].getConfig().name+")"+" info: " + json.tasks[i].info);
									}
									if (json.tasks[i].error) {
										this.log("task "+i+" ("+tasks[i].getConfig().name+")"+" error: " + json.tasks[i].error);
									}
									
									
								}
								
							
							}
							
							if (json.result){																			
								for (i=0;i<outputs.length;i++){
									var result = json.result;
									var output = outputs[i];
									var value = output.getValue();
									if (typeof(result[value.input.inputParams.name])!="undefined"){
										if(result[value.input.inputParams.name].url){
											var myResult = result[value.input.inputParams.name].url;
										}
										else{
											var myResult = result[value.input.inputParams.name];
										}
										value.input.inputParams.value = myResult;														
										output.setValue(value);
										output.setDone();
										if(output.getValue().input.type=="file"){
											if(myResult.endsWith('.m')||myResult.endsWith('.png')||myResult.endsWith('.jpg')||myResult.endsWith('.gif')||myResult.endsWith('.bmp')||myResult.endsWith('.svg')||myResult.endsWith('.tiff')){
												output.renderViewElement(myResult);
											}
											else{
											    output.renderViewElement(myResult);
											}
										}
									}
								}
								

				
							}
							if (json.state == "DONE") {
								this.log("Workflow execution finished");
                                pe.stop();
							    this.deleteTemporary();
							}
						}			
					}.bind(this),
					
					onFailure: function(transport){ 
						var response = transport.responseText || "no response text";
						var url = instanceURI;
						  if (transport.status==404) {	//remote instance finished execution						
						   pe.stop();
                				   this.returnToEditor();
						   this.log("404 error\nUrl "+url);
	
						   } else if (transport.status==400) {
						   alert("mistake in url "+url+"\n"+response);
						   this.log("mistake in url "+url+"\n"+response);
						   } else if (transport.status==500) { //remote instance stopped by another client
						   		this.log("remote instance stopped by another client");
								pe.stop();
								for (i = 0; i < this.layer.containers.length; i++) {
                					this.layer.containers[i].setReady();
            					}
						   } else {
							   alert('GET. Could not load data from url '+transport.status+"\n"+response);
							   this.log('GET. Could not load data from url '+transport.status+"\n"+response); }
						}.bind(this)
					});
				
				}.bind(this), 1);
	},
	
	stopRunningTasks: function(){
		for (i = 0; i < this.layer.containers.length; i++) {
			if (this.layer.containers[i].state == "RUNNING") {
				var task = this.layer.containers[i];
				new Ajax.Request (task.textarea.value+'?method=delete', {
					method:'post',
					onSuccess: function(transport){
					var response = transport.responseText || "no response text";
					this.log("Success! \n\n" + "Task stopped");
	           	
					}.bind(this),
					
					onFailure: function(transport){ 
					var response = transport.responseText || "no response text";
					var url = task.textarea.value+'?method=delete';
					if (transport.status==404) {
						//alert("404 error\nUrl "+url);
						this.log("404 error\nUrl "+url);
	
						} else if (transport.status==400) {
							alert("mistake in url "+url+"\n"+response);
							this.log("mistake in url "+url+"\n"+response);
						} else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response);  }
						}.bind(this)
				});
			}
		}
	},
	
	renderLoadPanel: function() {
	    if(!this.loadPanel) {
	       this.loadPanel = new widget.Panel('WiringEditor-loadPanel', {
	          fixedcenter: true,
	          draggable: true,
	          width: '500px',
	          visible: false,
	          modal: true
	       });
	       this.loadPanel.setHeader("Select workflow");
	       this.loadPanel.setBody("<div id='loadPanelBody'></div>");
	       this.loadPanel.render(document.body);
	    }

	 },

	updateLoadPanelList: function() {
		var list = WireIt.cn("ul");
		var filenames = new Array();
		if(lang.isArray(this.pipes)) {

			function sortByName(a, b) {
    			var x = a.name.toLowerCase();
    			var y = b.name.toLowerCase();
    			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
			}
			
			this.pipes.sort(sortByName);
						
		   for(var i = 0 ; i < this.pipes.length ; i++) {
		      var module = this.pipes[i];

		
			 var li = WireIt.cn('li',null,{cursor: 'pointer'},"<b>name:</b> " + module.name +" <b>description:</b> " + module.description +"<!--" + module.file+"-->");
		       Event.addListener(li, 'click', function(e,args) {
		         try {

					var html = Event.getTarget(e).innerHTML;
					var filename = html.split('<!--')[1].replace(new RegExp("[\\s]*","g"),'').replace(new RegExp("-->","g"),"");
					//alert("filename: " + filename);
					this.log("loading file " + filename);					
					this.loadSubmit(filename);
					
		         }
		         catch(ex) {
		            this.log("Exception: " + ex);
					if (console) {
						console.log(ex);
					}
		         }
		      }, this, true);
		      list.appendChild(li);
		   }
		}
		//list.sort();
		var panelBody = Dom.get('loadPanelBody');
		panelBody.innerHTML = "";
		panelBody.appendChild(list);
	},
	
	getValue: function() {
	 	
	    
	   var i;
	   var obj = {modules: [], wires: [], properties: null};
					
	   for( i = 0 ; i < this.layer.containers.length ; i++) {
	     	 	  
		  if (this.layer.containers[i].options.title == "Task"){
			obj.modules.push( {name: this.layer.containers[i].resourceJSON.name, value: this.layer.containers[i].getValue(), config: this.layer.containers[i].getConfig()});
		  }
		  
		  else if ((this.layer.containers[i].options.title == "Script")||(this.layer.containers[i].options.title == "JavaScript")||(this.layer.containers[i].options.title == "Python")){
			obj.modules.push( {name: this.layer.containers[i].name, value: this.layer.containers[i].getValue(), config: this.layer.containers[i].getConfig()});
			
		  }
		  
		  else if (this.layer.containers[i].getValue().input){ //input or output container
			if(this.layer.containers[i].getValue().input.inputParams.name){
				obj.modules.push( {name: this.layer.containers[i].getValue().input.inputParams.name, value: this.layer.containers[i].getValue(), config: this.layer.containers[i].getConfig()});
			}
			else{
				obj.modules.push({name: this.layer.containers[i].options.title, value: this.layer.containers[i].getValue(), config: this.layer.containers[i].getConfig()});
			}
			
		  }
		else {
		obj.modules.push({name: this.layer.containers[i].options.title, value: this.layer.containers[i].getValue(), config: this.layer.containers[i].getConfig()});
			
		}
				  
	   }
	
	   for( i = 0 ; i < this.layer.wires.length ; i++) {
	      var wire = this.layer.wires[i];
	
	      var wireObj = { 
	         src: {moduleId: WireIt.indexOf(wire.terminal1.container, this.layer.containers), terminal: wire.terminal1.options.name}, 
	         tgt: {moduleId: WireIt.indexOf(wire.terminal2.container, this.layer.containers), terminal: wire.terminal2.options.name},
			 color:this.layer.wires[i].options.color
	      };
	      obj.wires.push(wireObj);
	   }
	   
	   obj.properties = this.propertiesForm.getValue();
	    
	   return {
	      name: obj.properties.name,
	      working: obj
	   };
	 },
	
	getInputValues:function(){//Get values of all input containers and place them in a JSON object
		var obj = {};
		for (i = 0; i < this.layer.containers.length; i++) {
			if ((this.layer.containers[i].options.title == "input")&&(this.layer.containers[i].getValue().input.type!="file")){
				var containerName = this.layer.containers[i].getValue().input.inputParams.name;
				var value = this.layer.containers[i].getValue().input.inputParams.value;
				if((this.layer.containers[i].getValue().input.type=="integer")||(this.layer.containers[i].getValue().input.type=="number")){
						obj[containerName] = parseFloat(value);
				}
				else{
					obj[containerName] = value;
				}
				}
			else if ((this.layer.containers[i].options.title == "input")&&(this.layer.containers[i].getValue().input.type=="file")){
				var containerName = this.layer.containers[i].getValue().input.inputParams.name;
				var value = {"url":this.layer.containers[i].getValue().input.inputParams.value};
				obj[containerName] = value;
			}
		}
		return obj;
	},
	 
	onFocusedEvent: function (e, params) {
		var container = params[0];
		this.focusedContainer = container;
		var signatureField = this.taskPropertiesForm.getFieldByName("signature");
		if(container.textarea){
			signatureField.setValue(container.textarea.value);
		}
	}, 
	 
	loadWorkflow: function (pipe){
		if (this.loadPanel) {
			this.loadPanel.hide();
		}
		
		this.loadingPanel.show();
		document.body.style.cursor = 'wait';			
		this.loaded = false;
		 this.markSaved();
		 this.layer.removeAllContainers();
	     this.propertiesForm.clear();
		 this.taskPropertiesForm.clear();
		this.propertiesForm.setValue(pipe.properties);
	    if(lang.isArray(pipe.modules)) {
			// Containers
	       for(i = 0 ; i < pipe.modules.length ; i++) {
				
			var m = pipe.modules[i]; //container JSON	  
			var position = m.config.position;
			position = YAHOO.lang.JSON.stringify(position).replace(/-/g,"");
		  

	          if(this.modulesByName[m.config.type]) {
				if((m.config.type == "input")&&(!m.config.schema)){
					var type = m.value.input.type;
					var name = m.name;
					var containerConfig = '{"xtype":"WireIt.WebUIInputContainer","title":"input","fields":[{"type": "myType", "inputParams": {"label": "Value", "name": "input", "wirable": false, "value": {"type": "' + type + '", "inputParams": {"name":"' + name + '","typeInvite": "input value"}}}}],"position":'+position+'}';
			
						var container = this.layer.addContainer(YAHOO.lang.JSON.parse(containerConfig));
						if(m.config.constant=="true"){					
							container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[0].setValue(true);
							container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[2].value="true";	
						}
						container.setValue(m.value);
					//terminal
						var inputTerminal = container.addTerminal({
							xtype: "WireIt.util.WebUITerminalOutput",
							"name": name+":"+type,
							"ddConfig": {
								"type": type
							},
							"direction": [0, 1],
							"offsetPosition": {
								"left": 86,
								"bottom": -15
							}
						});
						container.setName(name);
				}
				 else if ((m.config.type == "input")&&(m.config.schema)) {
				 	var portJSON = m.config.schema;
					var type = m.value.input.type;
					var name = m.name;

					if ((type == "string") && (portJSON["enum"])) {//singleselect list
						if (!portJSON.options) {
							var list = YAHOO.lang.JSON.stringify(portJSON["enum"]);
						}
						else {
							var list = new Array;
							var inverse = new Array;
							var numbered = portJSON["enum"];
							for (j in portJSON.options) {
								list[j] = '"'+portJSON.options[j].label+'"';
								inverse[portJSON.options[j].label]=j;
							}
							list = '['+list+']';
						}
						
						var containerConfig = '{"xtype":"WireIt.WebUIInputContainer","title":"input","fields":[{"type": "select", "inputParams": {"name": "list","className":"listField","selectValues": '+list+'}},{"type": "myType", "inputParams": {"name": "input", "wirable": false, "value": {"type": "' + type + '", "inputParams": {"name":"' + name + '","typeInvite": "input value"}}}}],"position":'+position+'}';
																		
						var container = this.layer.addContainer(YAHOO.lang.JSON.parse(containerConfig));
						if(m.config.constant=="true"){					
							container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[0].setValue(true);
							container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[2].value="true";	
						}
						container.setValue(m.value);
						container.schema = portJSON;
						container.setValue(m.value);
						
						if (container.bodyEl.getElementsByClassName("listField")[0].getWidth() > container.el.getWidth()) {
							container.el.style.width = container.bodyEl.getElementsByClassName("listField")[0].getWidth() + 20 + 'px';
						}
						else {
							container.el.style.width=container.el.getWidth();
						}
						container.bodyEl.getElementsByClassName("inputEx-StringField-wrapper")[0].style.display='none';
					
						YAHOO.util.Event.addListener(container.bodyEl.getElementsByClassName("listField")[0],"change",function() {
							value = container.getValue();
							if (!portJSON.options) {
								value.input.inputParams.value = value.list;
							}
							else {
								value.input.inputParams.value = numbered[inverse[value.list]];
							}
							container.setValue(value);
							container.bodyEl.getElementsByClassName("inputEx-StringField-wrapper")[0].style.display='none';
						},this,true);
					
						var terminal = container.addTerminal({
							xtype: "WireIt.util.WebUITerminalOutput",
							"name": name+":"+type,
							"ddConfig": {
								"type": type
							},
							"direction": [0, 1],
							"offsetPosition": {
								"left": Math.floor((container.el.getWidth())/2)-15,
								"bottom": -15
							}
						});
						container.setName(name);
										
					}
					else if((type == "array")&&(portJSON.items["enum"])){//multiselect list
						var items = portJSON["items"];
						var listOptions = items["options"];
			
						var list = new Array;
						var inverse = new Array;
						var numbered = portJSON["enum"];
						var names = new Array;
			
						list = YAHOO.lang.JSON.stringify(items["enum"]);
						names[0] ='"select multiple.."';
						for (k=0;k<listOptions.length;k++) {
							names[k+1]='"'+listOptions[k].label+'"';
						}
						list = '["stub",'+list.split('[')[1];
						names = "["+names+"]"
			
						var containerConfig = '{"xtype":"WireIt.WebUIInputContainer","title":"input","fields":[{"type": "multiselect", "inputParams": {"name": "list", "className":"listField","selectValues":'+list+',"selectOptions":'+names+'}},{"type": "myType", "inputParams": {"name": "input", "wirable": false, "value": {"type": "' + type + '", "inputParams": {"name":"' + name + '","typeInvite": "input value"}}}}],"position":' + position + '}';
							var container = this.layer.addContainer(YAHOO.lang.JSON.parse(containerConfig));
							if(m.config.constant=="true"){					
								container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[0].setValue(true);
								container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[2].value="true";	
							}
						container.setValue(m.value);
							container.schema = portJSON;
							container.setValue(m.value);

								
							if (container.bodyEl.getElementsByClassName("listField")[0].getWidth() > container.el.getWidth()) {
								container.el.style.width = container.bodyEl.getElementsByClassName("listField")[0].getWidth() + 20 + 'px';
							}
					
								container.bodyEl.getElementsByClassName("inputEx-StringField-wrapper")[0].style.display='none';
										
								YAHOO.util.Event.addListener(container.el,"change",function() {
	
									if (container.bodyEl.getElementsByClassName("listField")[0].getWidth() > container.el.getWidth()) {
										container.el.style.width = container.bodyEl.getElementsByClassName("listField")[0].getWidth() + 20 + 'px';
										container.positionTerminals();
									}
										value = container.getValue();
										value.input.inputParams.value = YAHOO.lang.JSON.stringify(value.list);
										container.setValue(value);
										container.redrawAllWires();
										container.bodyEl.getElementsByClassName("inputEx-StringField-wrapper")[0].style.display='none';
										container.initState();
								},this,true);

								YAHOO.util.Event.addListener(container.bodyEl,"click",function() {

									if (container.bodyEl.getElementsByClassName("listField")[0].getWidth() > container.el.getWidth()) {
										container.el.style.width = container.bodyEl.getElementsByClassName("listField")[0].getWidth() + 20 + 'px';
										container.positionTerminals();
									}
										value = container.getValue();
										value.input.inputParams.value = YAHOO.lang.JSON.stringify(value.list);
										container.setValue(value);
										container.redrawAllWires();
										container.bodyEl.getElementsByClassName("inputEx-StringField-wrapper")[0].style.display='none';
										container.initState();
								},this,true);
		
					
								var inputTerminal = container.addTerminal({
									xtype: "WireIt.util.WebUITerminalOutput",
									"name": name+":"+type,
									"ddConfig": {
										"type": type
									},
									"direction": [0, 1],
									"offsetPosition": {
										"left": Math.floor((container.el.getWidth())/2)-15,
										"bottom": -15
									}
								});
								container.setName(name);
		
					}
					else {//plain types 							
							var containerConfig = '{"xtype":"WireIt.WebUIInputContainer","title":"input","fields":[{"type": "myType", "inputParams": {"label": "Value", "name": "input", "wirable": false, "value": {"type": "' + type + '", "inputParams": {"name":"' + name + '","typeInvite": "input value"}}}}],"position":'+position+'}';
							var container = this.layer.addContainer(YAHOO.lang.JSON.parse(containerConfig));
							if(m.config.constant=="true"){					
								container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[0].setValue(true);
								container.bodyEl.getElementsByClassName("constantCheckBox")[0].childNodes[2].value="true";	
							}
							container.setValue(m.value);
							container.schema = portJSON;
							container.setValue(m.value);

						//terminal
							var inputTerminal = container.addTerminal({
								xtype: "WireIt.util.WebUITerminalOutput",
								"name": name+":"+type,
								"ddConfig": {
									"type": type
								},
								"direction": [0, 1],
								"offsetPosition": {
									"left": 86,
									"bottom": -15
								}
							});
							container.setName(name);
							if (type == "file") {
								container.renderUploadLink();
							}
					}
				 }
				else if (m.config.type == "output") {
					if(m.config.schema){
						var portJSON = m.config.schema;
					}
					var type = m.value.input.type;
					var name = m.name;
					var containerConfig = '{"xtype":"WireIt.WebUIOutputContainer","title":"output","fields":[{"type": "myType", "inputParams": {"label": "Value", "name": "input", "wirable": false, "value": {"type": "' + type + '", "inputParams": {"name":"' + name + '","typeInvite": "input value"}}}}],"position":'+position+'}';
				 	var container = this.layer.addContainer(YAHOO.lang.JSON.parse(containerConfig));
					if (m.config.schema) {
						container.schema = portJSON;
					}
					container.setValue(m.value);
					
				//terminal
					var outputTerminal = container.addTerminal({
						xtype: "WireIt.util.WebUITerminalInput",
						"name": name+":"+type,
						"ddConfig": {
							"type": type
						},
						"direction": [0, -1],
						"offsetPosition": {
							"left": 86,
							"top": -15
						}
					});
					container.setName(name);
				}
				else {
					var baseContainerConfig = this.modulesByName[m.config.type].container;
					YAHOO.lang.augmentObject(m.config, baseContainerConfig);
					m.config.title = m.config.type;
					
					
					var container = this.layer.addContainer(m.config);
					Dom.addClass(container.el, "WiringEditor-module-" + m.config.type);
					container.setValue(m.value);
				}		 
				 
	          }
	          else {
	             throw new Error("WiringEditor: module '"+m.config.type+"' not found !");
	          }
	       }
	       
		 
		 }
		
		// Wires
		if(lang.isArray(pipe.wires)) {
			
			for(i = 0 ; i < pipe.wires.length; i++) {
				this.layer.addWire(pipe.wires[i]);
			}
			
		}
		
		for (i = 0; i < this.layer.containers.length; i++){
			var container = this.layer.containers[i];
			container.initState();
		}
		this.loaded = true;
		this.loadingPanel.hide();
		document.body.style.cursor = 'default';

			
	},
	
    deleteTemporary: function(){
		if(this.temporary==true){
			new Ajax.Request (location.href+'wf/'+this.saveFile+'?method=delete', {
				method:'post',
				onSuccess: function(transport){
				var response = transport.responseText || "no response text";
				this.log("Temporary file deleted");
				this.saveFile = undefined;
				this.IDForm.clear();
				this.propertiesForm.clear();
				this.temporary == undefined;
				
				}.bind(this),
	
				onFailure: function(transport){ 
					var response = transport.responseText || "no response text";
					var url = location.href+'wf/'+this.saveFile+'?method=delete';
					if (transport.status==404) {

						this.log("404 error\nUrl "+url);
	
						} else if (transport.status==400) {
							alert("mistake in url "+url+"\n"+response);
							this.log("mistake in url "+url+"\n"+response);
						} else {
						   alert('Could not load data from url '+transport.status+"\n"+response);
						   this.log('Could not load data from url '+transport.status+"\n"+response); }
						}.bind(this)
			});
		}
	},
	
	log: function(string){
		var nd = new Date();
		debugConsole = document.getElementById("console");
		debugConsole.innerHTML+= nd.getHours()+":"+nd.getMinutes()+":"+nd.getSeconds()+" "+string+ "\n";
		debugConsole.scrollTop = debugConsole.scrollHeight - debugConsole.clientHeight;
	},
	
	
	returnToEditor: function(){
        //reset states of containers to continue editing
        YAHOO.util.Event.addListener(document.getElementById("layer"), "click", function(){
            for (i = 0; i < this.layer.containers.length; i++) {
                this.layer.containers[i].setReady();
            }
            YAHOO.util.Event.removeListener(document.getElementById("layer"), "click");
			this.instanceForm.clear();
            
        }, this, true);
    }
		
});

})();
